package client

import (
	"context"
	"github.com/smallnest/rpcx/client"
	"github.com/smallnest/rpcx/protocol"
	"go.uber.org/zap"
	"sync"
	"time"
	"wzgames/internal/gloader"
	"wzgames/internal/model/gamep"
	"wzgames/internal/model/mcomm"
	"wzgames/internal/response"
	"wzgames/internal/services"
	"wzgames/pkg/logger"
)

// cat rpc client

var (
	catPool *client.XClientPool
	catOnce sync.Once
)

func InitCatClient() {
	option := client.DefaultOption
	option.ConnectTimeout = 5 * time.Second
	option.Heartbeat = true
	option.HeartbeatInterval = 15 * time.Second
	option.Retries = 2
	option.SerializeType = protocol.ProtoBuffer
	d := gloader.NewServiceDiscovery(services.RPCxServiceCat)
	catPool = client.NewXClientPool(3, services.RPCxServiceCat, client.Failover, client.RoundRobin, d, option)
}

func GetCatClient() client.XClient {
	if catPool == nil {
		catOnce.Do(func() {
			InitCatClient()
		})
	}
	return catPool.Get()
}

func CloseCatClient() {
	if catPool != nil {
		catPool.Close()
	}
}

// GetSonyFlakeID SonyFlakeID
func GetSonyFlakeID() uint64 {
	rpcCtx, cancelFn := context.WithTimeout(context.Background(), 5*time.Second)
	req := &mcomm.ID{}
	reply := &mcomm.IdReply{}
	err := GetCatClient().Call(rpcCtx, "GenSonyFlakeID", req, reply)
	cancelFn()
	if err != nil {
		logger.Error("[Client] get sonyFlakeId fail on GetSonyFlakeID", zap.Error(err))
		return 0
	}

	return reply.RetID
}

// GetID 基于数据库的ID生成
func GetID(biz int64, step uint64) uint64 {
	rpcCtx, cancelFn := context.WithTimeout(context.Background(), 5*time.Second)
	req := &mcomm.ID{BizID: biz, Step: step}
	reply := &mcomm.IdReply{}
	err := GetCatClient().Call(rpcCtx, "GenID", req, reply)
	cancelFn()
	if err != nil {
		logger.Error("[Client] get get id fail on GetID", zap.Error(err))
		return 0
	}

	return reply.RetID
}

// NodeBootRecord 应用节点启动登记
func NodeBootRecord(nodeId, dateline int64) {
	rpcCtx, cancelFn := context.WithTimeout(context.Background(), 5*time.Second)
	req := &mcomm.SysNodeBoot{
		NodeId:   nodeId,
		Dateline: dateline,
	}
	reply := &mcomm.CodeRet{}
	err := GetCatClient().Call(rpcCtx, "NodeBootHistory", req, reply)
	cancelFn()
	if err != nil {
		logger.Error("[Client] record node boot history fail on rpc call NodeBootHistory", zap.Error(err))
	}
}

// GetGameCurrency 获取币种方案
func GetGameCurrency(gcId int64) (*gamep.GameCurrency, int16) {
	reply := &gamep.GameCurrReply{}
	rpcCtx, cancelFn := context.WithTimeout(context.Background(), 10*time.Second)
	err := GetCatClient().Call(rpcCtx, "GetGameCurrency", &mcomm.ID{BizID: gcId}, reply)
	cancelFn()
	if err != nil {
		logger.Error("[Client] get Game Currency fail", zap.Int64("GcId", gcId), zap.Error(err))
		return nil, response.ErrInternal
	}

	if reply.Code != 0 {
		return nil, int16(reply.Code)
	}

	return reply.GameCurr, 0
}
